package org.paradigmshift.cumulusfracto.filesystem;

import org.alfresco.jlan.server.SrvSession;
import org.alfresco.jlan.server.auth.CifsAuthenticator;
import org.alfresco.jlan.server.auth.ClientInfo;
import org.apache.log4j.Logger;
import com.google.gdata.client.GoogleAuthTokenFactory.UserToken;
import com.google.gdata.client.GoogleService.AccountDisabledException;
import com.google.gdata.client.GoogleService.CaptchaRequiredException;
import com.google.gdata.client.GoogleService.InvalidCredentialsException;
import com.google.gdata.client.docs.DocsService;
import com.google.gdata.util.AuthenticationException;


public class CumulusFractoCifsAuthenticator extends CifsAuthenticator {
	
	private static final Logger log = Logger.getLogger( CumulusFractoCifsAuthenticator.class );
	
	public CumulusFractoCifsAuthenticator() {
		
		if ( log.isDebugEnabled() ) log.debug( "Cumulus Fracto Cifs Authenticator created." );
	}
	
	/**
	 * Authenticate a user
	 * 
	 * @param client Client information
	 * @param sess Server session
	 * @param alg Encryption algorithm
	 */
	public int authenticateUser( ClientInfo client, SrvSession sess, int alg ) {
		
		if ( !(client instanceof CumulusFractoClientInfo) ) return CifsAuthenticator.AUTH_DISALLOW;
		
		CumulusFractoClientInfo cfClient = (CumulusFractoClientInfo) client;
		
		// Not sure if this block is really necessary, but keeping it for now just to be safe
		// No guests allowed! Sorry... but it's the rules...
		if ( client.isGuest() ) return AUTH_DISALLOW;
		
//		// Check if this is an SMB/CIFS null session logon.  The null session will only be allowed to connect to the IPC$ named pipe share.
//		if ( client.isNullSession() && sess instanceof SMBSrvSession ) {
//			
//			// TODO verify if this is necessary
//			if ( log.isDebugEnabled() ) log.debug( "Null CIFS logon allowed." );
//			return CifsAuthenticator.AUTH_ALLOW;
//		}
		
		DocsService docsService = cfClient.getDocsService();
		
		// Check if the client is already authenticated, and it is not a null logon
		String authToken = cfClient.getAuthToken();
		if ( authToken != null && client.getLogonType() != ClientInfo.LogonNull ) {
			
			if ( log.isDebugEnabled() ) log.debug( "Using authToken to login." );
			docsService.setUserToken( authToken );
		}
		else {
			
			try {
				
				docsService.setUserCredentials( cfClient.getUserName(), cfClient.getPasswordAsString() );
				
				UserToken userToken = (UserToken) docsService.getAuthTokenFactory().getAuthToken();
				authToken = userToken.getValue();
				
				// TODO: Save auth token to database
				
					// If username doesn't exist in database, create it and token
				
					// otherwise update the token for the given username
			}
			catch ( CaptchaRequiredException cre ) {
				
				// TODO: send user to the captcha web page
				if ( log.isDebugEnabled() ) log.debug( "Captcha required." );
			}
			catch ( InvalidCredentialsException ice ) {
				
				if ( log.isDebugEnabled() ) log.debug( "Bad password." );
				return AUTH_BADPASSWORD;
			}
			catch ( AccountDisabledException ade ) {
				
				if ( log.isDebugEnabled() ) log.debug( "Account disabled." );
				return AUTH_ACCDISABLED;
			}
			catch ( AuthenticationException ae ) {
				
				if ( log.isDebugEnabled() ) log.debug( "Authentication disallowed." );
				return AUTH_DISALLOW;
			}
		}
		
		if ( log.isDebugEnabled() ) log.debug( "Authenticated user: " + client.getUserName() );
		return CifsAuthenticator.AUTH_ALLOW;
	}
}
